﻿module Test

open NUnit.Framework
open CssTypes
open CssParser
open FParsec

let floatBetweenBrackets : Parser<double> = pstring "[" >>. pfloat .>> pstring "]"
let floatBetweenBracketsWs : Parser<double> =  ws >>. pstring "[" >>. ws >>. pfloat .>> ws .>> pstring "]" .>> ws


[<TestFixture>]
type testCssParsing() =

    (* expects a valid parse and returns value *)
    member self.parse<'a> (parser:Parser<'a>) src : 'a =
        let result = run parser src 
        match result with
        | Success(result,_,_) -> result

    [<Test>]
    member self.testParse() =
        let result = self.parse floatBetweenBrackets "[1.2]"
        Assert.AreEqual(1.2, result)


    [<Test>]
    member self.testParseWhitespace() =
        let result = self.parse floatBetweenBracketsWs " [ 1.3 ] "
        Assert.AreEqual(1.3, result)

    [<Test>]
    member self.testParseSelector() =
        let result = self.parse nodeSelector """body """
        Assert.AreEqual(NodeSelector(TypeSelector("body"), []), result)

    [<Test>]
    member self.testParseSelectorWClass() =
        let result = self.parse nodeSelector """body.main """
        Assert.AreEqual(NodeSelector(TypeSelector("body"), [ClassQualifier(["main"])]), result)

    [<Test>]
    member self.testParseSelectorWMultipleClass() =
        let result = self.parse nodeSelector """*.a.b """
        Assert.AreEqual(NodeSelector(UniversalTypeSelector,[ClassQualifier(["a";"b"])]), result)

    [<Test>]
    member self.testParseSelectorMultipleQualifiers() =
        let result = self.parse nodeSelector """[a=b]#c.d """
        Assert.AreEqual(NodeSelector(UniversalTypeSelector,[AttributeValue("a","b");IdQualifier("c");ClassQualifier(["d"])]), result)

    [<Test>]
    member self.testParseContextSelector() =
        let result = self.parse selector """a *.b > c"""
        let (ContextualSelector(anchor, ChildSelector(parent))) = result
        let (NodeSelector(TypeSelector("c"),[])) = anchor
        let (ContextualSelector(parentNodeSelector, DescendentSelector(ancestor))) = parent
        let (SimpleSelector(NodeSelector(TypeSelector("a"),[]))) = ancestor
        ()

    [<Test>]
    member self.testParseSelectorList() =
        let result = self.parse selectorList "body, b c, d.e, #f, input[type=checkbox], .h.i > j  "
        Assert.AreEqual(6, result.Length)
        let (SimpleSelector(nodeSelector)) = result.[4]
        Assert.AreEqual(NodeSelector(TypeSelector("input"),[AttributeValue("type","checkbox")]), nodeSelector)

    [<Test>]
    member self.testParseCss() =
        let rules = self.parse ruleset """body, b c, d.e, #f, input[type=checkbox], .h.i
            , a:hover 
            { 
                display:inline; background-color: #00ff00
            }  """
        let (Ruleset(Rule(selectors,declarations))) = rules
        Assert.AreEqual(2, declarations.Length)

    [<Test>]
    member self.testParseNumeric() =
        let decl = self.parse declaration """margin-right:.5em"""
        let (Declaration(propName,[(Measure(0.5M, "em"))], false)) = decl
        ()

    [<Test>]
    member self.testParseNegUrl() =
        let decl = self.parse declaration """background:url(/images/srpr/nav_logo80.png)"""
        let (Declaration(propName,[(Url("/images/srpr/nav_logo80.png"))], false)) = decl
        ()

    [<Test>]
    member self.testParseMinus() =
        let decl = self.parse declaration """background:0 -258px -x-repeat(2, 3 4) -x-prop1"""
        let (Declaration(propName,terms,_)) = decl
        Assert.AreEqual(Number(0M), terms.[0])
        Assert.AreEqual(Measure(-258M,"px"), terms.[1])

    [<Test>]
    member self.testParseGarbageTerm() =
        let decl = self.parse declaration """filter:progid:DXImageTransform.Microsoft.gradient(startColorStr='#4d90fe',EndColorStr='#4787ed');"""
        ()


    [<Test>]
    member self.testParseCssWithRules() =
        let result = self.parse stylesheet """@charset "utf8";
            @import "absd";
            body { background-color: #00ff00 }
            @media (max-width: 700px) {
                body {
                    background-color: #fff;
                }
            } 
            a { background-color: #00ff00 }          
            """
        let (Statements(_,stmts)) = result
        let (Ruleset(Rule(selectors,declarations))) = stmts.[0]
        Assert.AreEqual(1, declarations.Length)


    [<Test>]
    member self.testParseMediaRule() =
        let result = parseStyleSheet """
        @media all{.gb1{margin-right:.5em;vertical-align:top}#gbar{float:left}}
        """
        ()


